package com.nuctech.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * 异常处理工具类
 *
 * @author lilu
 * @date 2020年4月29日
 * @since 1.0.0
 */
public class Exceptions {

	/**
	 * 将CheckedException转换为UncheckedException
	 *
	 * @author lilu
	 * @date 2020年4月29日 下午2:00:10
	 * @since 1.0.0
	 *
	 * @param e
	 * @return
	 */
	public static RuntimeException unchecked(Throwable e) {
		if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
			|| e instanceof NoSuchMethodException) {
			return new IllegalArgumentException(e);
		} else if (e instanceof InvocationTargetException) {
			return new RuntimeException(((InvocationTargetException) e).getTargetException());
		} else if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		} else {
			return new RuntimeException(e);
		}
	}

	/**
	 * 代理异常解包
	 *
	 * @author lilu
	 * @date 2020年4月29日 下午1:59:42
	 * @since 1.0.0
	 *
	 * @param wrapped 包装过得异常
	 * @return 解包后的异常
	 */
	public static Throwable unwrap(Throwable wrapped) {
		Throwable unwrapped = wrapped;
		while (true) {
			if (unwrapped instanceof InvocationTargetException) {
				unwrapped = ((InvocationTargetException) unwrapped).getTargetException();
			} else if (unwrapped instanceof UndeclaredThrowableException) {
				unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();
			} else {
				return unwrapped;
			}
		}
	}

	/**
	 * 将ErrorStack转化为String，用于打印到日志中
	 *
	 * @author lilu
	 * @date 2020年4月29日 下午1:59:16
	 * @since 1.0.0
	 *
	 * @param ex
	 * @return
	 */
	public static String getStackTraceAsString(Throwable ex) {
		// try-with-resource语法糖 处理机制
		try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
			ex.printStackTrace(pw);
			pw.flush();
			sw.flush();
			return sw.toString();
		} catch (Exception ignored) {
			throw new RuntimeException(ignored.getMessage(), ignored);
		}
	}

}
